package tencentmap

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	v1 "golang-sgg-daijia/api/v1"
	"golang-sgg-daijia/pkg/log"
	"io"
	"math"
	"net/http"
	"strconv"
)

type MapClient interface {
	RoutesDriving(ctx context.Context, req *v1.CalculateDrivingLineForm) (*v1.DrivingLineVo, error)
}

type mapClient struct {
	logger *log.Logger
	conf   *viper.Viper
}

func NewMapClient(
	logger *log.Logger,
	conf *viper.Viper,
) MapClient {
	return &mapClient{
		logger: logger,
		conf:   conf,
	}
}

func (r *mapClient) RoutesDriving(ctx context.Context, req *v1.CalculateDrivingLineForm) (*v1.DrivingLineVo, error) {
	key := r.conf.GetString("security.tencentmap.key")
	//开始位置
	// 经纬度：比如 北纬40 东经116
	from := fmt.Sprintf("%s,%s",
		strconv.FormatFloat(req.StartPointLatitude, 'g', -1, 32),
		strconv.FormatFloat(req.StartPointLongitude, 'g', -1, 32),
	)
	//结束位置
	to := fmt.Sprintf("%s,%s",
		strconv.FormatFloat(req.EndPointLatitude, 'g', -1, 32),
		strconv.FormatFloat(req.EndPointLongitude, 'g', -1, 32),
	)
	//定义调用腾讯地址
	url := fmt.Sprintf("https://apis.map.qq.com/ws/direction/v1/driving/?from=%s&to=%s&key=%s", from, to, key)

	resp, err := http.Get(url)
	if err != nil || resp.StatusCode > 299 {
		r.logger.WithContext(ctx).Error("mapClient|RoutesDriving|http.Get", zap.Any("data", map[string]interface{}{
			"resp": resp,
		}), zap.Error(err))
		return nil, err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		r.logger.WithContext(ctx).Error("mapClient|RoutesDriving|io.ReadAll", zap.Error(err))
		return nil, err
	}
	resp.Body.Close()
	result := &v1.TencentMapDrivingResp{}
	err = json.Unmarshal(body, result)
	if err != nil {
		r.logger.WithContext(ctx).Error("mapClient|RoutesDriving|json.Unmarshal", zap.Error(err))
		return nil, err
	}
	if result.Status != 0 {
		err = errors.New("地图服务调用失败")
		r.logger.WithContext(ctx).Error("mapClient|RoutesDriving", zap.Error(err))
		return nil, err
	}
	distance := result.Result.Routes[0].Distance / 1000 // 单位从米转为千米
	drivingLineVo := &v1.DrivingLineVo{
		Distance: math.Round(distance*100) / 100, // 保留两位，距离*100理论上不会溢出
		Duration: result.Result.Routes[0].Duration,
		Polyline: result.Result.Routes[0].Polyline,
	}
	return drivingLineVo, nil
}
